package org.finegold.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.finegold.core.http.util.HttpUtil;
import org.finegold.core.tool.jackson.JsonUtil;
import org.finegold.core.tool.utils.Func;
import org.finegold.core.tool.utils.RandomType;
import org.finegold.core.tool.utils.ThreadUtil;
import org.finegold.dto.Root;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <B>Description:</B> TODO <br>
 *
 * @Author QinXueFeng
 * @Date 2022-01-04 10:39
 * @Version 1.0.0
 * @VersionList <pre>
 *    版本        修改人        修改日期        修改描述
 *    ------------------------------------------------------------
 *    1.0.0       QinXueFeng        2022-01-04 10:39        create
 *    ------------------------------------------------------------
 * </pre>
 */
public class ReptileUtil {

    /**
     * 爬虫入口
     * @param shareUrl
     * @param downUrl
     * @throws IOException
     */
    public static void reptile(String shareUrl, String downUrl) throws IOException {
        Map<String, String> map = Maps.newHashMap();
        String userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
        map.put("user-agent", userAgent);
        String userId = getUserId(shareUrl, userAgent);
        String sign = SignUtil.getSign(userId);
        String url1="https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid="+userId+"&count=100&max_cursor=0&_signature="+sign;
        //像js一样，通过id 获取文章列表元素对象
        List<Map<String, String>> list = Lists.newArrayList();
        getStringBuffer(list, map, url1, 0);
        List<Map<String, String>> list1 = Lists.newArrayList();
        List<String> urlList = Lists.newArrayList();
        try {
            for (Map<String, String> m : list) {
                Map<String, String> map1 = Maps.newHashMap();
                map1.put("desc", m.get("desc"));
                map1.put("url", m.get("url"));
                map1.put("img", m.get("img"));
                map1.put("author", m.get("author"));
                urlList.add(m.get("url"));
                list1.add(map1);
            }
            downloadNetNio(urlList,downUrl);

            //downloadNetBio(urlList,downUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取用户id
     * @param url
     * @param userAgent
     * @return
     * @throws IOException
     */
    private static String getUserId(String url, String userAgent) throws IOException {
        Request.Builder builder = new Request.Builder();
        builder.addHeader("user-agent", userAgent);
        Request request = builder.get().url(url).build();
        OkHttpClient okHttpClient = new OkHttpClient.Builder().followRedirects(false).build();
        Response response = okHttpClient.newCall(request).execute();
        String location = response.headers().get("Location");
        String substring = location.substring(location.indexOf("user/") + 5, location.indexOf("?"));
        return substring;
    }

    /**
     * 获取带有视频地址的集合
     * @param list
     * @param map
     * @param url1
     * @param max_cursor
     */
    private static void getStringBuffer(List<Map<String, String>> list, Map<String, String> map, String url1, long max_cursor) {
        String url = url1.replace("max_cursor=0", "max_cursor=" + max_cursor);
        String json1 = HttpUtil.get(url, map, null);
        Root root = JsonUtil.parse(json1, Root.class);
        if ("0".equals(String.valueOf(root.getStatus_code()))) {
            if (Func.isEmpty(root.getAweme_list())) {
                return;
            } else {
                root.getAweme_list().forEach(l -> {
                    Map<String, String> map1 = Maps.newHashMap();
                    map1.put("desc", l.getDesc());
                    if (Func.isNotEmpty(l.getVideo().getDynamic_cover().getUrl_list())
                            && Func.isNotEmpty(l.getAuthor().getAvatar_thumb().getUrl_list()) && Func.isNotEmpty(l.getVideo().getPlay_addr().getUrl_list())) {
                        map1.put("img", l.getVideo().getDynamic_cover().getUrl_list().get(0));
                        map1.put("author", l.getAuthor().getAvatar_thumb().getUrl_list().get(0));
                        map1.put("url", l.getVideo().getPlay_addr().getUrl_list().get(0));
                        list.add(map1);
                    }

                });
            }
        }
        if (root.getHas_more() && root.getMax_cursor() != 0) {
            getStringBuffer(list, map, url1, root.getMax_cursor());
        }
    }

    private static void downloadNetNio(List<String> list,String downUrl) {
        AtomicInteger atomicInteger = new AtomicInteger();
        for (String src : list) {
            new Thread(() -> {
                try {
                    ReadableByteChannel readableByteChannel = null;
                    FileOutputStream fileOutputStream = null;
                    URL url = new URL(src);
                    readableByteChannel = Channels.newChannel(url.openStream());
                    fileOutputStream = new FileOutputStream(downUrl + atomicInteger.addAndGet(1) + ".mp4", true);
                    fileOutputStream.getChannel()
                            .transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
                    fileOutputStream.close();
                    readableByteChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    private static void downloadNetBio(List<String> list,String downUrls) {
        for (String src : list) {
            new Thread(() -> {
                // 下载网络文件
                int bytesum = 0;
                int byteread = 0;
                try {
                    URL url = new URL(src);
                    String key = UUID.randomUUID().toString();
                    URLConnection conn = url.openConnection();
                    InputStream inStream = conn.getInputStream();
                    FileOutputStream fs = new FileOutputStream(downUrls + key + ".mp4");
                    byte[] buffer = new byte[1204];
                    while ((byteread = inStream.read(buffer)) != -1) {
                        bytesum += byteread;
                        fs.write(buffer, 0, byteread);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
